﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.Core.FlowEngine
 * 唯一标识：5ac7108d-3b86-4e84-b24a-7593360a1704
 * 文件名：VampirewalWorkFlowEngineExtension
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2023/10/13 14:01:40
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

global using SqlSugar;
global using System.ComponentModel;
global using System.ComponentModel.DataAnnotations;
global using Vampirewal.Core.Attributes;


namespace Vampirewal.Core.FlowEngine;

/// <summary>
/// 流程引擎扩展
/// </summary>
public static class VampirewalWorkFlowEngineExtension
{
    /// <summary>
    /// 注册并使用流程引擎(服务器端)
    /// </summary>
    /// <param name="services"></param>
    /// <param name="Option">服务端配置</param>
    public static void AddVampirewalWorkFlowEngineServer<T>(this IServiceCollection services, Action<IVampirewalWorkFlowEngineOption> Option) where T : IVampirewalWorkFlowEngineServer
    {
        VampirewalWorkFlowEngineOption op = new VampirewalWorkFlowEngineOption();
        Option?.Invoke(op);

        //注册流程引擎配置
        services.AddSingleton<IVampirewalWorkFlowEngineOption>(op);
        //注册服务端自己使用的配置项，不暴露给使用方进行配置
        services.AddSingleton<IVampirewalWorkFlowEngineOptionForServer>(op);
        //注册流程引擎服务
        services.AddSingleton(typeof(IVampirewalWorkFlowEngineServer), typeof(T));
        //注册流程执行方式到服务
        services.AddSingleton<IVampirewalFlowUnitExcutionMode>(op.ExcuteMode);
    }
}

/// <summary>
/// 流程引擎服务端配置
/// </summary>
public interface IVampirewalWorkFlowEngineOption
{
    /// <summary>
    /// 通过数据库加载流程
    /// <para>需要在程序启动之后调用，初始化的时候，无法获取到SqlSugarRepository</para>
    /// </summary>
    /// <param name="rep"></param>
    /// <returns></returns>
    Task LoadFlowByDb(SqlSugarRepository<Flow> rep);

    /// <summary>
    /// 通过JSON加载流程
    /// <para>可以在初始化的时候调用</para>
    /// </summary>
    /// <param name="Path"></param>
    /// <returns></returns>
    Task LoadFlowByJson(string Path);

    /// <summary>
    /// 注册FlowType
    /// </summary>
    /// <param name="FlowType"></param>
    /// <param name="FlowName"></param>
    /// <returns></returns>
    IVampirewalWorkFlowEngineOption RegirstFlowType(int FlowType, string FlowName);

    /// <summary>
    /// 构建流程
    /// </summary>
    /// <param name="builder"></param>
    IVampirewalWorkFlowEngineOption FlowBuilder(Action<IVampirewalFlowBuilder> builder);

    /// <summary>
    /// 注册流程节点执行方式实现
    /// </summary>
    /// <typeparam name="Mode"></typeparam>
    /// <returns></returns>
    IVampirewalWorkFlowEngineOption RegisterFlowUnitExcutionMode<Mode>() where Mode : IVampirewalFlowUnitExcutionMode;
}

/// <summary>
/// 服务端使用的配置
/// </summary>
internal interface IVampirewalWorkFlowEngineOptionForServer : IVampirewalWorkFlowEngineOption
{
    /// <summary>
    /// 根据FlowType获取Flow信息
    /// </summary>
    /// <param name="FlowType"></param>
    /// <returns></returns>
    Flow GetFlowByType(int FlowType);

    /// <summary>
    /// 通过FlowId获取Flow信息
    /// </summary>
    /// <param name="FlowId"></param>
    /// <returns></returns>
    Flow GetFlowById(string  FlowId);

    
}

/// <summary>
/// 流程引擎配置
/// </summary>
internal class VampirewalWorkFlowEngineOption : IVampirewalWorkFlowEngineOption, IVampirewalWorkFlowEngineOptionForServer
{
    /// <summary>
    /// 构造函数
    /// </summary>
    public VampirewalWorkFlowEngineOption()
    {
        Flows = new List<Flow>();
        FlowTypeDic = new Dictionary<int, string>();
    }

    /// <summary>
    /// 流程集合
    /// </summary>
    internal List<Flow> Flows { get; set; }

    /// <summary>
    /// 通过数据库加载流程
    /// </summary>
    public async Task LoadFlowByDb(SqlSugarRepository<Flow> rep)
    {
        Flows = await rep.ToListAsync();

        foreach (var flow in Flows)
        {
            flow.Units = await rep.Change<FlowUnit>().Where(w => w.BillId == flow.BillId).OrderBy(o => o.UnitIndex).ToListAsync();
            flow.Links = await rep.Change<FlowLink>().Where(w => w.FlowId == flow.BillId).ToListAsync();
            flow.Parameters=await rep.Change<FlowParam>().Where(w => w.BillId == flow.BillId).ToListAsync();
        }
    }

    /// <summary>
    /// 通过JSON加载流程
    /// </summary>
    /// <param name="Path"></param>
    /// <returns></returns>
    public async Task LoadFlowByJson(string Path)
    {
        await Task.Run(() =>
        {
            using (System.IO.StreamReader sr = System.IO.File.OpenText(Path))
            {
                string json = sr.ReadToEnd();

                Flows = JsonSerializer.Deserialize<List<Flow>>(json);

                if (Flows == null)
                {
                    throw new Exception($"无法加载路径:{Path}的Json文件!");
                }
            }
        });
    }

    /// <summary>
    /// 流程类型字典
    /// </summary>
    internal Dictionary<int, string> FlowTypeDic { get; set; }

    /// <summary>
    /// 注册FlowType
    /// </summary>
    /// <param name="FlowType"></param>
    /// <param name="FlowName"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public IVampirewalWorkFlowEngineOption RegirstFlowType(int FlowType, string FlowName)
    {
        if (!FlowTypeDic.TryAdd(FlowType, FlowName))
        {
            throw new Exception($"存在重复的FlowType:{FlowType}");
        }

        return this;
    }

    /// <summary>
    /// 根据FlowType获取Flow信息
    /// </summary>
    /// <param name="FlowType"></param>
    /// <returns></returns>
    public Flow GetFlowByType(int FlowType)
    {
        return Flows.FirstOrDefault(f => f.FlowType == FlowType);
    }

    /// <summary>
    /// 通过FlowId获取Flow信息
    /// </summary>
    /// <param name="FlowId"></param>
    /// <returns></returns>
    public Flow GetFlowById(string FlowId)
    {
        return Flows.FirstOrDefault(f => f.BillId == FlowId);
    }

    public IVampirewalFlowUnitExcutionMode ExcuteMode { get; set; }

    /// <summary>
    /// 构建流程
    /// </summary>
    /// <param name="builder"></param>
    public IVampirewalWorkFlowEngineOption FlowBuilder(Action<IVampirewalFlowBuilder> builder)
    {
        VampirewalFlowBuilder _builder = new VampirewalFlowBuilder();
        builder.Invoke(_builder);


        if (Flows.Any(a=>a.FlowCode.Equals(_builder.FlowInfo.FlowCode)))
        {
            throw new Exception($"存在重复的FlowCode:{_builder.FlowInfo.FlowCode}");
        }

        if (Flows.Any(a =>  a.FlowType == _builder.FlowInfo.FlowType))
        {
            throw new Exception($"存在重复的FlowType:{_builder.FlowInfo.FlowType}");
        }

        Flows.Add(_builder.FlowInfo);

        return this;
    }

    public IVampirewalWorkFlowEngineOption RegisterFlowUnitExcutionMode<Mode>() where Mode : IVampirewalFlowUnitExcutionMode
    {
        ExcuteMode = Activator.CreateInstance(typeof(Mode)) as IVampirewalFlowUnitExcutionMode;

        if (ExcuteMode == null)
        {
            throw new Exception("流程节点执行方式不能为null！请自行实现 IVampirewalFlowUnitExcutionMode");
        }

        return this;
    }

}